#!/usr/bin/env vpython3
# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Script to ensure that the same tags are in all expectation files."""

from __future__ import print_function

import argparse
import logging
import os
import sys

TAG_HEADER = """\
# OS
# tags: [ android android-lollipop android-marshmallow android-nougat
#             android-pie android-r android-s android-t
#         chromeos
#         fuchsia
#         linux ubuntu
#         mac highsierra mojave catalina bigsur monterey ventura
#         win win8 win10 ]
# Devices
# tags: [ android-nexus-5x android-pixel-2 android-pixel-4
#             android-pixel-6 android-shield-android-tv android-sm-a135m
#             android-sm-a235m
#         chromeos-board-amd64-generic chromeos-board-kevin chromeos-board-eve
#             chromeos-board-jacuzzi chromeos-board-octopus
#         fuchsia-board-astro fuchsia-board-sherlock fuchsia-board-qemu-x64 ]
# Platform
# tags: [ desktop
#         mobile ]
# Browser
# tags: [ android-chromium android-webview-instrumentation
#         debug debug-x64
#         release release-x64
#         fuchsia-chrome web-engine-shell
#         lacros-chrome cros-chrome ]
# GPU
# tags: [ amd amd-0x6613 amd-0x679e amd-0x67ef amd-0x6821 amd-0x7340
#         apple apple-apple-m1 apple-angle-metal-renderer:-apple-m1
#         arm
#         google google-0xffff google-0xc0de
#         intel intel-gen-9 intel-gen-12 intel-0xa2e intel-0xd26 intel-0xa011
#               intel-0x3e92 intel-0x3e9b intel-0x5912 intel-0x9bc5
#         nvidia nvidia-0xfe9 nvidia-0x1cb3 nvidia-0x2184
#         qualcomm ]
# Architecture
# tags: [ mac-arm64 mac-x86_64 ]
# Decoder
# tags: [ passthrough no-passthrough ]
# Browser Target CPU
# tags: [ target-cpu-64 target-cpu-32 target-cpu-31 ]
# ANGLE Backend
# tags: [ angle-disabled
#         angle-d3d9 angle-d3d11
#         angle-metal
#         angle-opengl angle-opengles
#         angle-swiftshader
#         angle-vulkan ]
# Skia Renderer
# tags: [ renderer-skia-dawn
#         renderer-skia-gl
#         renderer-skia-vulkan
#         renderer-software ]
# Driver
# tags: [ mesa_lt_19.1
#         mesa_ge_21.0 ]
# ASan
# tags: [ asan no-asan ]
# Display Server
# tags: [ display-server-wayland display-server-x ]
# OOP-Canvas
# tags: [ oop-c no-oop-c ]
# WebGPU Backend Validation
# tags: [ dawn-backend-validation dawn-no-backend-validation ]
# WebGPU Adapter
# tags: [ webgpu-adapter-default webgpu-adapter-swiftshader ]
# Clang coverage
# tags: [ clang-coverage no-clang-coverage ]
# results: [ Failure RetryOnFailure Skip Slow ]
"""

TAG_HEADER_BEGIN =\
    '# BEGIN TAG HEADER (autogenerated, see validate_tag_consistency.py)'
TAG_HEADER_END = '# END TAG HEADER'

EXPECTATION_DIR = os.path.join(os.path.dirname(__file__), 'gpu_tests',
                               'test_expectations')


def Validate():
  retval = 0
  for f in (f for f in os.listdir(EXPECTATION_DIR) if f.endswith('.txt')):
    with open(os.path.join(EXPECTATION_DIR, f)) as infile:
      content = infile.read()
      start_index = content.find(TAG_HEADER_BEGIN)
      end_index = content.find(TAG_HEADER_END)
      if (start_index < 0 or end_index < 0
          or content[start_index + len(TAG_HEADER_BEGIN) + 1:end_index] !=
          TAG_HEADER):
        retval = 1
        logging.error(
            'Expectation file %s does not have a tag/result header consistent '
            'with the source of truth.', f)
  if retval:
    logging.error(
        'See %s for the expected header or run it in the "apply" mode to apply '
        'the source of truth to all expectation files.', __file__)
  return retval


def Apply():
  retval = 0
  for f in (f for f in os.listdir(EXPECTATION_DIR) if f.endswith('.txt')):
    filepath = os.path.join(EXPECTATION_DIR, f)
    with open(filepath) as infile:
      content = infile.read()
    start_index = content.find(TAG_HEADER_BEGIN)
    if start_index < 0:
      retval = 1
      logging.error(
          'Expectation file %s did not have tag header start string "%s".', f,
          TAG_HEADER_BEGIN)
      continue
    end_index = content.find(TAG_HEADER_END)
    if end_index < 0:
      retval = 1
      logging.error(
          'Expectation file %s did not have tag header end string "%s".', f,
          TAG_HEADER_END)
      continue
    content = (content[:start_index + len(TAG_HEADER_BEGIN)] + '\n' +
               TAG_HEADER + content[end_index:])
    with open(filepath, 'w') as outfile:
      outfile.write(content)
  return retval


def main():
  parser = argparse.ArgumentParser(
      description=('Validate that all test expectation tags are identical '
                   'across all expectation files or apply the source of truth '
                   'to all expectation files.'))
  parser.add_argument('function',
                      choices=['apply', 'validate'],
                      help='What the script should do.')
  args = parser.parse_args()
  if args.function == 'apply':
    return Apply()
  return Validate()


if __name__ == '__main__':
  sys.exit(main())
